package com.lwlk.util.rubbish;

import com.lwlk.util.flow.Try;
import com.lwlk.util.functional.Common;
import com.lwlk.util.functional.Method1;
import com.lwlk.util.functional.TypeTransformer;

/* 重构那个垃圾Switch类 */

public class Switch {

    private static class SwitchBinder<SwitchType, ElementType, SwitchDataType> {
        private final SwitchAccepter<SwitchType, ElementType,
                TypeTransformer<ElementType, SwitchType>> accepter;
        private final SwitchData<SwitchDataType> holder;
        public SwitchBinder(SwitchAccepter<SwitchType, ElementType,
                TypeTransformer<ElementType, SwitchType>> accepter,
                            SwitchData<SwitchDataType> holder) {
            this.accepter = accepter;
            this.holder = holder;
        }
    }

    /* 绑定分支数据 */

    private static class SwitchData<SwitchDataType> {
        private final SwitchDataType data;
        public SwitchData(SwitchDataType data) {
            this.data = data;
        }
        public SwitchDataType getData() {
            return data;
        }
    }

    /* 判断分支 */

    private static class SwitchAccepter<SwitchType, ElementType,
            TransformerType extends TypeTransformer<ElementType, SwitchType>> {
        private final Method1<Boolean, SwitchType> judge;
        private final TransformerType transformer;
        public SwitchAccepter(Method1<Boolean, SwitchType> judge, TransformerType transformer) {
            this.judge = judge;
            this.transformer = transformer;
        }
        public boolean accept(ElementType element) {
            // 尝试转型
            Try.ChoiceResult<SwitchType> result = Try.choice(() -> transformer.call(element), () -> null);
            // 转型成功后进行逻辑判定 否则拒绝接受
            return result.hasException() ? false : judge.call(result.getResult());
        }
    }

    /* 直接应用相等语义的 Symbol */

    private static class SwitchSymbol<T> extends SwitchAccepter<T, T, TypeTransformer<T, T>> {
        public SwitchSymbol(Method1<Boolean, T> judge, TypeTransformer<T, T> transformer) {
            super(judge, transformer);
        }
    }

    /* 构建 Switch Symbol 的帮助类 */

    private static class SwitchSymbolBuilder<T> {
        public SwitchSymbol<T> build(T e) {
            return new SwitchSymbol<>(e::equals, Common::identity);
        }
    }

    /* 常用的提前定义一下 */

    private static final SwitchSymbolBuilder<Integer> IntegerSymbol = new SwitchSymbolBuilder<>();

    private static final SwitchSymbolBuilder<String> StringSymbol  = new SwitchSymbolBuilder<>();
}
